package cn.iocoder.yudao.module.hs.job;

import cn.hutool.core.collection.CollUtil;
import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
import cn.iocoder.yudao.framework.quartz.core.handler.JobHandler;
import cn.iocoder.yudao.module.hs.controller.admin.entryorder.vo.TripartiteEntryOrderSaveReqVO;
import cn.iocoder.yudao.module.hs.controller.admin.shiporder.vo.ShipOrderSaveReqVO;
import cn.iocoder.yudao.module.hs.dal.dataobject.picktaskmaterialdetail.PickTaskMaterialDetailDO;
import cn.iocoder.yudao.module.hs.dal.dataobject.shiporder.ShipOrderDO;
import cn.iocoder.yudao.module.hs.dal.dataobject.warehouse.WarehouseDO;
import cn.iocoder.yudao.module.hs.enums.shiporder.ShipOrderStatusEnum;
import cn.iocoder.yudao.module.hs.enums.warehouse.WarehouseTypeEnum;
import cn.iocoder.yudao.module.hs.netty.RFIDData;
import cn.iocoder.yudao.module.hs.service.device.DeviceService;
import cn.iocoder.yudao.module.hs.service.entryorder.EntryOrderService;
import cn.iocoder.yudao.module.hs.service.picktaskmaterialdetail.PickTaskMaterialDetailService;
import cn.iocoder.yudao.module.hs.service.shiporder.ShipOrderService;
import cn.iocoder.yudao.module.hs.service.warehouse.WarehouseService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import java.time.LocalDateTime;
import java.util.*;
import java.util.stream.Collectors;

/**
 * 1.运输中状态的出库单根据RFID扫描处理，进行三方仓库的入库操作
 * 2.出库中状态的出库单根据RFID扫描处理，更新为运输中状态
 * 3.待出库区状态的出库单根据RFID扫描处理，更新为出库中状态
 */
@Component
@Slf4j
public class OrderStatusChangeJob implements JobHandler {

    @Resource
    private ShipOrderService shipOrderService;

    @Resource
    private EntryOrderService entryOrderService;

    @Resource
    private PickTaskMaterialDetailService pickTaskMaterialDetailService;

    @Resource
    private WarehouseService warehouseService;

    @Resource
    private DeviceService deviceService;

    @Override
    public String execute(String param) {
        List<RFIDData> rfidList = RFIDData.getLastRFIDList();
        if (CollUtil.isEmpty(rfidList)) {
            log.info("## RFID扫描故障，未获取RFID上报数据");
            return "## RFID扫描故障，未获取RFID上报数据";
        }
//        log.info("## 由拣货完成转为出库中状态RFID扫描任务开始：");
//        // 只处理是待出库区
//        List<String> waitingAreaDeviceIds = deviceService.getDeviceByIds(null).stream().filter(DeviceDO::getWaitingArea)
//                .map(DeviceDO::getCode).collect(Collectors.toList());
//        List<RFIDData> waitingAreaRfidList = new ArrayList<>();
//        if (CollUtil.isNotEmpty(waitingAreaDeviceIds)) {
//            waitingAreaRfidList = rfidList.stream().filter(rfidData -> waitingAreaDeviceIds.contains(rfidData.getDeviceId()))
//                    .collect(Collectors.toList());
//        }
//        int shipOrderToOutingCount = 0;
//        if (CollectionUtil.isNotEmpty(waitingAreaRfidList)) {
//            List<ShipOrderDO> pickOverShipOrderList = shipOrderService.getShipOrderListByStatus(ShipOrderStatusEnum.PICK_OVER.getStatus());
//            if (CollUtil.isNotEmpty(pickOverShipOrderList)) {
//                shipOrderToOutingCount = shipOrderToOutingHandle(pickOverShipOrderList, waitingAreaRfidList);
//            }
//        }
//        log.info("## 由拣货完成转为出库中状态的数量：{}", shipOrderToOutingCount);
        log.info("## 三方仓由已收货转为已入库状态RFID扫描任务开始：");
        List<String> status = new ArrayList<>();
        status.add(ShipOrderStatusEnum.RECEIVED.getStatus());
        status.add(ShipOrderStatusEnum.ENTRYING.getStatus());
        List<ShipOrderDO> toEntryShipOrderList = shipOrderService.getShipOrderListByStatus(status, WarehouseTypeEnum.PRODUCTION.getType());
        int thirdEntryOrderRfidCount = 0;
        if (CollUtil.isNotEmpty(toEntryShipOrderList)) {
            thirdEntryOrderRfidCount = shipOrderToEntryHandle(toEntryShipOrderList, rfidList);
        }
        log.info("## 三方仓由已收货转为已入库状态的数量：{}", thirdEntryOrderRfidCount);

        log.info("## 生产仓由出库中转为运输中 或 已出库状态RFID扫描任务开始：");
        int toTransportingCount = 0;
        status = new ArrayList<>();
        status.add(ShipOrderStatusEnum.OUTING.getStatus());
        List<ShipOrderDO> toTransportingShipOrderList = shipOrderService.getShipOrderListByStatus(status, WarehouseTypeEnum.PRODUCTION.getType());
        if (CollUtil.isNotEmpty(toTransportingShipOrderList)) {
            toTransportingCount = toTransportingHandle(toTransportingShipOrderList, rfidList);
        }
        log.info("## 生产仓由出库中转为运输中 或 已出库状态的数量：{}", toTransportingCount);
        return "执行成功";
    }

    /**
     * 出库中处理
     *
     * @param pickOverShipOrderList 拣货完成的出库单
     * @param rfidList              RFID 数据
     * @return 处理数量
     */
    private int shipOrderToOutingHandle(List<ShipOrderDO> pickOverShipOrderList, List<RFIDData> rfidList) {
        log.info("## 由拣货完成转为出库中状态RFID扫描任务，rfidList {}", rfidList);
        log.info("## 由拣货完成转为出库中状态RFID扫描任务，出库中数量 {}，明细 {}", pickOverShipOrderList.size(), pickOverShipOrderList);
        int shipOrderOutCount = 0;
        for (ShipOrderDO shipOrder : pickOverShipOrderList) {
            try {
                // 查询仓库是否有待出库区
                WarehouseDO warehouse = warehouseService.getWarehouse(shipOrder.getWarehouseId());
                if (!warehouse.getHaveWaitingArea()) {
                    continue;
                }
                Set<String> collectRfidSet = getRfidCodeSet(shipOrder);
                if (CollUtil.isEmpty(collectRfidSet)) {
                    continue;
                }
                log.info("## 由拣货完成转为出库中状态RFID扫描任务，出库单 {} 对应的 RFID清单 {}", shipOrder.getCode(), collectRfidSet);
                boolean isOut = true;
                Set<String> rfidCodeSet = rfidList.stream()
                        .filter(Objects::nonNull)
                        .map(RFIDData::getRfidCode)
                        .collect(Collectors.toSet());

                if (!Collections.disjoint(rfidCodeSet, collectRfidSet)) {
                    isOut = false;
                }
                if (isOut) {
                    shipOrder.setStatus(ShipOrderStatusEnum.OUTING.getStatus());
                    shipOrder.setOutingTime(LocalDateTime.now());
                    shipOrderService.updateShipOrder(BeanUtils.toBean(shipOrder, ShipOrderSaveReqVO.class));
                    shipOrderOutCount++;
                }
            } catch (Exception e) {
                log.error("## 出库单拣货完成状态RFID扫描任务异常：{}", e.getMessage(), e);
            }
        }
        return shipOrderOutCount;
    }

    /**
     * 出库中状态的出库单根据RFID扫描处理，更新为已出库
     *
     * @param outingShipOrderList
     * @param rfidList
     */
    private int toTransportingHandle(List<ShipOrderDO> outingShipOrderList, List<RFIDData> rfidList) {
        log.info("## 由出库中转为运输中状态RFID扫描任务，rfidList {}", rfidList);
        log.info("## 由出库中转为运输中状态RFID扫描任务，出库中数量 {}，明细 {}", outingShipOrderList.size(), outingShipOrderList);
        int shipOrderTransportCount = 0;
        for (ShipOrderDO shipOrder : outingShipOrderList) {
            try {
                Set<String> collectRfidSet = getRfidCodeSet(shipOrder);
                if (CollUtil.isEmpty(collectRfidSet)) {
                    continue;
                }
                log.info("## 由出库中转为运输中状态RFID扫描任务，出库单 {} 对应的 RFID清单 {}", shipOrder.getCode(), collectRfidSet);
                boolean isOut = true;
                Set<String> rfidCodeSet = rfidList.stream()
                        .filter(Objects::nonNull)
                        .map(RFIDData::getRfidCode)
                        .collect(Collectors.toSet());

                if (!Collections.disjoint(rfidCodeSet, collectRfidSet)) {
                    isOut = false;
                }
                if (isOut) {
                    shipOrder.setStatus(ShipOrderStatusEnum.TRANSPORTING.getStatus());
                    shipOrder.setTransportingTime(LocalDateTime.now());
                    shipOrderService.updateShipOrder(BeanUtils.toBean(shipOrder, ShipOrderSaveReqVO.class));
                    shipOrderTransportCount++;
                }
            } catch (Exception e) {
                log.error("## 出库单出库中状态RFID扫描任务异常：{}", e.getMessage(), e);
            }
        }
        return shipOrderTransportCount;
    }

    /**
     * 获取出库单的RFID码Set集合
     *
     * @param shipOrder
     * @return
     */
    private Set<String> getRfidCodeSet(ShipOrderDO shipOrder) {
        List<PickTaskMaterialDetailDO> pickTaskMaterialDetailList = pickTaskMaterialDetailService.getPickTaskMaterialDetailList(shipOrder.getId());
        if (CollUtil.isEmpty(pickTaskMaterialDetailList)) {
            log.info("未查询到出库单的拣货明细记录，shipOrderId：{}", shipOrder.getId());
            return null;
        }
        return pickTaskMaterialDetailList.stream().map(PickTaskMaterialDetailDO::getRfidCode).collect(Collectors.toSet());
    }


    /**
     * 运输中状态的出库单根据RFID扫描处理，进行三方仓库的入库操作
     *
     * @param receiveShipOrderList
     * @param rfidList
     */
    private int shipOrderToEntryHandle(List<ShipOrderDO> receiveShipOrderList, List<RFIDData> rfidList) {
//        log.info("## 由运输中转为已入库状态RFID扫描任务，数据上传rfidList {}", rfidList);
        log.info("## 由运输中转为已入库状态RFID扫描任务，运输中数量 {}，明细 {}", receiveShipOrderList.size(), receiveShipOrderList);
        int thirdEntryOrderRfidCount = 0;
        for (ShipOrderDO shipOrder : receiveShipOrderList) {
            Set<String> collectRfidSet = getRfidCodeSet(shipOrder);
            if (CollUtil.isEmpty(collectRfidSet)) {
                continue;
            }
            log.info("## 由运输中转为已入库状态RFID扫描任务，出库单 {} 对应的 RFID清单 {}", shipOrder.getCode(), collectRfidSet);
            // 按 rfidCode 分组，并且每组内按 reportTime 倒序排列
            Map<String, List<RFIDData>> rfidCodeToListDataMap = rfidList.stream()
                    .sorted(Comparator.comparing(RFIDData::getReportTime, Comparator.nullsLast(Comparator.reverseOrder())))
                    .collect(Collectors.groupingBy(
                            RFIDData::getRfidCode,
                            Collectors.toList()
                    ));
            for (String rfidCode : collectRfidSet) {
                if (rfidCodeToListDataMap.containsKey(rfidCode)) {
                    List<RFIDData> rfidDataList = rfidCodeToListDataMap.get(rfidCode);
                    if (CollUtil.isNotEmpty(rfidDataList)) {
                        RFIDData rfidData = rfidDataList.get(0);
                        TripartiteEntryOrderSaveReqVO tripartiteEntryOrderSaveReqVO = new TripartiteEntryOrderSaveReqVO();
                        tripartiteEntryOrderSaveReqVO.setCode(rfidData.getRfidCode());
                        tripartiteEntryOrderSaveReqVO.setDeviceCode(rfidData.getDeviceId());
                        log.info("## 三方仓入库状态RFID扫描任务，处理order = {}， 处理rfid = {}, 基站ID = {}", shipOrder.getCode(), rfidData.getRfidCode(), rfidData.getDeviceId());
                        try {
                            entryOrderService.createTripartiteEntryOrder(tripartiteEntryOrderSaveReqVO);
                        } catch (Exception e) {
                            log.error("## 三方仓入库状态RFID扫描任务异常：{}", e.getMessage(), e);
                        }
                        thirdEntryOrderRfidCount++;
                    }
                }
            }
        }
        return thirdEntryOrderRfidCount;
    }
}
